<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import Motion from "../utils/motion";
import { message } from "@/utils/message";
import { useUserStoreHook } from "@/store/modules/user";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { initRouter, getTopMenu } from "@/router/utils";
import { postPlatformLogin } from "@/api/user";
import Refresh from "~icons/ri/refresh-line";

type QrStatus = "ready" | "scanned" | "authorizing" | "success" | "expired";

const QR_EXPIRE_SECONDS = 90;

const userStore = useUserStoreHook();
const router = useRouter();

const status = ref<QrStatus>("ready");
const countdown = ref(QR_EXPIRE_SECONDS);
const OPEN_ID_KEY = "mock_platform_openid";
const TICKET_KEY = "mock_platform_ticket";

const ticket = ref(sessionStorage.getItem(TICKET_KEY) || generateTicket());
const openId = ref(localStorage.getItem(OPEN_ID_KEY) || generateOpenId());
if (!localStorage.getItem(OPEN_ID_KEY)) {
  localStorage.setItem(OPEN_ID_KEY, openId.value);
}
let timer: number | undefined;
const DEFAULT_AVATAR =
  "https://avatars.dicebear.com/api/identicon/mock-qr-user.svg?background=%23e0f2fe";
const DEFAULT_NICKNAME = "扫码体验用户";

const statusLabel = computed(() => {
  switch (status.value) {
    case "ready":
      return "等待扫码";
    case "scanned":
      return "已扫码，待确认";
    case "authorizing":
      return "授权中...";
    case "success":
      return "登录成功";
    case "expired":
      return "二维码已失效";
    default:
      return "";
  }
});

const statusTagType = computed(() => {
  switch (status.value) {
    case "ready":
      return "info";
    case "scanned":
      return "warning";
    case "authorizing":
      return "success";
    case "success":
      return "success";
    case "expired":
      return "danger";
    default:
      return "info";
  }
});

const qrImage = computed(() => {
  const base = `THIRD-PARTY LOGIN\nTICKET:${ticket.value}`;
  const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'>
    <defs>
      <linearGradient id='g' x1='0%' x2='100%' y1='0%' y2='100%'>
        <stop offset='0%' stop-color='#2563eb'/>
        <stop offset='100%' stop-color='#0ea5e9'/>
      </linearGradient>
    </defs>
    <rect width='220' height='220' rx='24' fill='url(#g)'/>
    <rect x='26' y='26' width='168' height='168' rx='16' fill='white' opacity='0.92'/>
    <text x='50%' y='92%' dominant-baseline='middle' text-anchor='middle'
      font-family='monospace' font-size='12' fill='#0f172a'>${ticket.value}</text>
  </svg>`;
  return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}#${base}`;
});

const isExpired = computed(() => status.value === "expired");
const canSimulateScan = computed(() => status.value === "ready");
const canConfirm = computed(() => status.value === "scanned");

const onBack = () => {
  userStore.SET_CURRENTPAGE(0);
};

function clearTimer() {
  if (timer) {
    window.clearInterval(timer);
    timer = undefined;
  }
}

function generateTicket() {
  return Math.random().toString(36).slice(2, 10).toUpperCase();
}

function generateOpenId() {
  return `mock-open-${Math.random().toString(36).slice(2, 10)}`;
}

function refreshCode(showTip = true) {
  clearTimer();
  ticket.value = generateTicket();
  sessionStorage.setItem(TICKET_KEY, ticket.value);
  countdown.value = QR_EXPIRE_SECONDS;
  status.value = "ready";
  timer = window.setInterval(() => {
    if (countdown.value <= 0) {
      expireCode();
      return;
    }
    countdown.value -= 1;
  }, 1000);
  if (showTip) {
    message("已生成新的模拟二维码", { type: "info" });
  }
}

function expireCode() {
  clearTimer();
  status.value = "expired";
  message("模拟二维码已失效，请重新生成", { type: "warning" });
}

function simulateScan() {
  if (!canSimulateScan.value) {
    return;
  }
  status.value = "scanned";
  message("已模拟第三方扫码，请在第三方完成授权确认", { type: "info" });
}

async function simulateAuthorize() {
  if (!canConfirm.value) return;
  status.value = "authorizing";
  clearTimer();
  await new Promise(resolve => window.setTimeout(resolve, 800));
  await completeMockLogin();
}

async function completeMockLogin() {
  try {
    const res = await postPlatformLogin({
      ticket: ticket.value,
      nickname: DEFAULT_NICKNAME,
      avatar: DEFAULT_AVATAR,
      client: "buyer",
      openid: openId.value
    });

    userStore.handleAuthResult(res);

    if (!res?.success) {
      status.value = "ready";
      message(res?.msg ?? "模拟登录失败", { type: "error" });
      refreshCode(false);
      return;
    }

    const payload = (res.data ?? {}) as Record<string, any>;
    if (payload.partial) {
      status.value = "success";
      message(res.msg ?? "已进入补充流程", { type: "success" });
      return;
    }

    await initRouter();
    let targetPath = "/welcome";
    try {
      const target = getTopMenu(true);
      if (target?.path) {
        targetPath = target.path;
      }
    } catch (error) {
      console.warn("获取默认路由失败，使用兜底路径", error);
    }
    await router.push(targetPath);
    status.value = "success";
    message(res.msg ?? "模拟第三方登录成功", { type: "success" });
  } catch (error: any) {
    console.error("模拟登录失败", error);
    status.value = "ready";
    message(error?.message ?? "模拟登录失败，请重试", { type: "error" });
    refreshCode(false);
  }
}

onMounted(() => {
  refreshCode(false);
});

onBeforeUnmount(() => {
  clearTimer();
});
</script>

<template>
  <Motion>
    <div class="qr-wrapper">
      <div class="qr-card">
        <div class="qr-image">
          <img :src="qrImage" alt="Mock QR Code" />
          <div v-if="isExpired" class="qr-mask">
            <span>二维码已失效</span>
          </div>
        </div>
        <div class="qr-status">
          <el-tag :type="statusTagType" size="small" effect="dark">
            {{ statusLabel }}
          </el-tag>
          <span v-if="status === 'ready'">
            使用测试第三方客户端扫码，{{ countdown }}s 后过期
          </span>
          <span v-else-if="status === 'scanned'">
            已模拟扫码，请点击下方「模拟确认登录」继续
          </span>
          <span v-else-if="status === 'authorizing'">
            正在模拟第三方授权，请稍候...
          </span>
          <span v-else-if="status === 'success'">登录成功，正在跳转...</span>
          <span v-else>二维码已过期，请点击下方按钮重新生成</span>
        </div>
        <div class="qr-meta">
          Ticket: <code>{{ ticket }}</code>
        </div>
        <el-button
          type="primary"
          plain
          :icon="useRenderIcon(Refresh)"
          @click="refreshCode()"
        >
          {{ isExpired ? "重新生成二维码" : "刷新二维码" }}
        </el-button>
      </div>

      <div class="qr-simulator">
        <h4>测试用第三方授权流程</h4>
        <ol>
          <li>点击「模拟扫码」，表示第三方应用已扫描二维码。</li>
          <li>点击「模拟确认登录」，将向平台回传授权结果，并直接完成登录。</li>
          <li>如需重新体验，可刷新二维码或返回账号登录。</li>
        </ol>
        <div class="simulator-actions">
          <el-button
            type="primary"
            :disabled="!canSimulateScan"
            @click="simulateScan"
          >
            模拟扫码
          </el-button>
          <el-button
            type="success"
            :disabled="!canConfirm"
            @click="simulateAuthorize"
          >
            模拟确认登录
          </el-button>
          <el-button
            v-if="status === 'scanned'"
            type="danger"
            plain
            @click="expireCode"
          >
            模拟取消
          </el-button>
        </div>
      </div>

      <div class="qr-back">
        <el-button type="default" @click="onBack">返回账号登录</el-button>
      </div>
    </div>
  </Motion>
</template>

<style scoped>
.qr-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 28px 0 16px;
  width: 100%;
}

.qr-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
  padding: 20px 24px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.08);
  width: 100%;
  max-width: 320px;
}

.qr-image {
  position: relative;
  width: 220px;
  height: 220px;
  border-radius: 24px;
  overflow: hidden;
}

.qr-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.qr-mask {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 23, 42, 0.65);
  color: #fff;
  font-size: 16px;
  letter-spacing: 1px;
}

.qr-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: #475569;
  font-size: 13px;
  text-align: center;
}

.qr-meta {
  font-size: 12px;
  color: #94a3b8;
}

.qr-meta code {
  padding: 2px 6px;
  background: rgba(148, 163, 184, 0.15);
  border-radius: 6px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}

.qr-simulator {
  width: 100%;
  max-width: 320px;
  padding: 14px 18px;
  border-radius: 16px;
  background: rgba(15, 23, 42, 0.04);
  backdrop-filter: blur(6px);
  color: #475569;
  font-size: 13px;
  line-height: 1.6;
}

.qr-simulator h4 {
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: 600;
  color: #1e293b;
}

.qr-simulator ol {
  padding-left: 18px;
  margin: 0 0 12px;
}

.simulator-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}

.qr-back {
  display: flex;
  justify-content: center;
  margin-top: 8px;
}
</style>
